﻿using System;
using HDM.NexusEngine.Core;

namespace HDM.NexusEngine.Shooter
{
    public class Enemy : Entity
    {
        private const double SCALE = 0.3;
        private const double HIT_FLASH_TIME = 0.25;
        private double _hitFlashCountDown;
        private readonly EffectsManager _effectsManager;
        private readonly Random _random = new Random();
        private double _shootCountDown;
        private readonly BulletManager _bulletManager;
        private readonly Texture _bulleTexture;
        private PlayerCharacter _player;

        public int Health { get; set; }

        public bool IsDead { get { return Health == 0; } }

        public Path Path { get; set; }

        public double MaxTimeToShoot { get; set; }

        public double MinTimeToShoot { get; set; }

        public Enemy(TextureManager textureManager, EffectsManager effectsManager, BulletManager bulletManager, PlayerCharacter player)
        {
            _player = player;
            _bulletManager = bulletManager;
            _bulleTexture = textureManager.Get("bullet");
            MaxTimeToShoot = 12;
            MinTimeToShoot = 1;
            RestartShootCountDown();

            _effectsManager = effectsManager;
            Health = 50; // default health value.
            //_sprite.Texture = textureManager.Get("enemy_ship");
            //_sprite.SetScale(SCALE, SCALE);
            // Make it face the player.
            _sprite.SetRotation(Math.PI);
            // Put it somewhere easy to see.
            _sprite.SetPosition(200, 0);
        }

        public void Update(double elapsedTime)
        {
            if (Path != null)
            {
                Path.UpdatePosition(elapsedTime, this);
            }

            if (_hitFlashCountDown != 0)
            {
                _hitFlashCountDown = Math.Max(0, _hitFlashCountDown - elapsedTime);
                var scaledTime = 1 - (_hitFlashCountDown/HIT_FLASH_TIME);
                _sprite.SetColor(new Color(1, 1, (float)scaledTime, 1));
            }

            _shootCountDown = _shootCountDown - elapsedTime;
            if (_shootCountDown <= 0)
            {
                var bullet = new Bullet(_bulleTexture);
                var currentPosition = _sprite.GetPosition();
                var bulletDir = _player.GetPosition() - currentPosition;
                bulletDir = Vector.Normalize(bulletDir);
                bullet.Direction = bulletDir;
                bullet.Speed = 350;
                bullet.SetPosition(_sprite.GetPosition());
                bullet.SetColor(new Color(1, 0, 0, 1));
                _bulletManager.EnemyShoot(bullet);
                RestartShootCountDown();
            }
        }

        public void Render(Renderer renderer)
        {
            renderer.DrawSprite(_sprite);
            //Render_Debug();
        }

        public void RestartShootCountDown()
        {
            _shootCountDown = MinTimeToShoot + (_random.NextDouble() * MaxTimeToShoot);
        }

        public void SetPosition(Vector position)
        {
            _sprite.SetPosition(position);
        }

        public void SetTexture(Texture texture)
        {
            _sprite.Texture = texture;
        }

        public void SetScale(double scale)
        {
            _sprite.SetScale(scale, scale);
        }

        internal void OnCollision(PlayerCharacter player)
        {
            // Handle collision with player.
        }

        internal void OnCollision(Bullet bullet)
        {
            // If the ship is already dead then ignore any more bullets.
            if (Health == 0) return;

            Health = Math.Max(0, Health - 25);
            _hitFlashCountDown = HIT_FLASH_TIME; // half
            _sprite.SetColor(new Color(1, 1, 0, 1));

            if (Health == 0) OnDestroyed();
        }

        private void OnDestroyed()
        {
            // Kill the enemy here.
            _effectsManager.AddExplosion(_sprite.GetPosition());
        }
    }
}